# coding:utf-8

"""
object.__str__(self)
通过 str(object) 以及内置函数 format() 和 print() 调用以生成一个对象的“非正式”或格式良好的字符串表示。返回值必须为一个 字符串 对象。

object.__getattr__(self, name)
当默认属性访问因引发 AttributeError 而失败时被调用 (可能是调用 __getattribute__() 时由于 name 不是一个实例属性或 self 的类关系树
中的属性而引发了 AttributeError；或者是对 name 特性属性调用 __get__() 时引发了 AttributeError)。此方法应当返回（找到的）属性值或
是引发一个 AttributeError 异常。

object.__setattr__(self, name, value)
此方法在一个属性被尝试赋值时被调用。这个调用会取代正常机制（即将值保存到实例字典）。
name 为属性名称， value 为要赋给属性的值。

object.__call__(self[, args...])
此方法会在实例作为一个函数被“调用”时被调用；如果定义了此方法，则 x(arg1, arg2, ...) 就大致可以被改写为
type(x).__call__(x, arg1, ...)。

"""


class Test(object):
    def __str__(self):
        return 'this is a test class'

    def __getattr__(self, key):
        return '这个key：{}并不存在'.format(key)

    def __setattr__(self, key, value):
        # if key not in self.__dict__:
        self.__dict__[key] = value
        return self.__dict__

    def __call__(self, a):
        print('call func will start')
        return a


t = Test()
print(t)  # this is a test class
print(t.a)  # 这个key：a并不存在
print(t.b)  # 这个key：b并不存在
t.name = '小慕'
print(t.name)  # 小慕
print(t('dewei'))  # call func will start dewei


class Test2(object):
    def __init__(self, attr=''):
        self.__attr = attr

    def __call__(self, name):
        # print('key is {}'.format(self.__attr))
        return name

    def __getattr__(self, key):
        if self.__attr:
            key = '{}.{}'.format(self.__attr, key)
        else:
            key = key
        print(key)
        return Test2(key)


t2 = Test2()
name = t2.a.b.c('dewei')
print(name)  # dewei
